/*
 * Copyright (c) 2022-2023 Termony Co., Ltd. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without modification,
 * are permitted provided that the following conditions are met:
 *
 * 1. Redistributions of source code must retain the above copyright notice, this list of
 *    conditions and the following disclaimer.
 *
 * 2. Redistributions in binary form must reproduce the above copyright notice, this list
 *    of conditions and the following disclaimer in the documentation and/or other materials
 *    provided with the distribution.
 *
 * 3. Neither the name of the copyright holder nor the names of its contributors may be used
 *    to endorse or promote products derived from this software without specific prior written
 *    permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#include "los_interrupt.h"
#include "los_context.h"
#include "los_debug.h"
#include "los_hook.h"
#include "los_task.h"
#include "los_sched.h"
#include "los_memory.h"
#include "los_membox.h"
#if (LOSCFG_CPUP_INCLUDE_IRQ == 1)
#include "los_cpup.h"
#endif

#include "securec.h"
#include "los_arch_cpu.h"
#include "los_arch_gic.h"
#include "los_arch_interrupt.h"

#ifdef __GNUC__
LITE_OS_SEC_VEC
#endif

/* 异常寄存器结构. */
EXC_CONTEXT_S g_exc = {0};
/* 异常信息控制块. */
ExcInfo g_excInfo = {0};
/* 中断嵌套计数器. */
volatile UINTPTR g_intCount = 0;
/* 中断控制块. */
static struct {
    struct {
        HWI_PROC_FUNC fn;
        VOID *parm;
    } handler[OS_HWI_MAX_NUM];
    UINT32 curHwiNum;
#if (LOSCFG_DEBUG_TOOLS == 1)
    CHAR *name[OS_HWI_MAX_NUM];
    UINT32 triggerCnt[OS_HWI_MAX_NUM];
#endif
} g_hwiCb;


UINT32 ArchIntLock(VOID)
{
    UINT32 intSave;

    __asm__ __volatile__("MRS %0, CPSR\n"
                         "CPSID I\n"
                         "DSB\n"
                         "ISB"
                         : "=r"(intSave) :: "memory");

    return intSave;
}

VOID ArchIntRestore(UINT32 intSave)
{
    __asm__ __volatile__("MSR CPSR_c, %0" :: "r"(intSave));
}

UINT32 ArchIntUnLock(VOID)
{
    UINT32 intSave;

    __asm__ __volatile__("CPSIE I\n"
                         "DSB\n"
                         "ISB\n"
                         "MRS %0, CPSR\n"
                         : "=r"(intSave) :: "memory");

    return intSave;
}

/* 设置目标CPU. */
STATIC UINT32 HwiSetTargetCPU(HWI_HANDLE_T hwiNum, UINT32 cpuId)
{
    if (hwiNum >= OS_HWI_MAX_NUM) {
        return OS_ERRNO_HWI_NUM_INVALID;
    }

    if (hwiNum >= (HWI_HANDLE_T) HalGicGetMaxIrqNum()) {
        return OS_ERRNO_HWI_NUM_INVALID;
    }

    HalGicIrqSetTargetCpu(LOSCFG_PLATFORM_GIC_SEQUENCE, hwiNum, (1UL << cpuId));
    return LOS_OK;
}

/* 设置中断优先级. */
STATIC UINT32 HwiSetPriority(HWI_HANDLE_T hwiNum, UINT8 priority)
{
    if (hwiNum >= OS_HWI_MAX_NUM) {
        return OS_ERRNO_HWI_NUM_INVALID;
    }

    if (priority > OS_HWI_PRIO_LOWEST) {
        return OS_ERRNO_HWI_PRIO_INVALID;
    }

    if (hwiNum >= (HWI_HANDLE_T) HalGicGetMaxIrqNum()) {
        return OS_ERRNO_HWI_NUM_INVALID;
    }

    HalGicSetIrqPriority(LOSCFG_PLATFORM_GIC_SEQUENCE, hwiNum, priority);
    return LOS_OK;
}

/* 中断使能. */
STATIC UINT32 HwiUnmask(HWI_HANDLE_T hwiNum)
{
    if (hwiNum >= OS_HWI_MAX_NUM) {
        return OS_ERRNO_HWI_NUM_INVALID;
    }

    if (hwiNum >= (HWI_HANDLE_T) HalGicGetMaxIrqNum()) {
        return OS_ERRNO_HWI_NUM_INVALID;
    }

    HalGicIrqUmask(LOSCFG_PLATFORM_GIC_SEQUENCE, hwiNum);
    return LOS_OK;
}

/* 中断禁止. */
STATIC UINT32 HwiMask(HWI_HANDLE_T hwiNum)
{
    if (hwiNum >= OS_HWI_MAX_NUM) {
        return OS_ERRNO_HWI_NUM_INVALID;
    }

    if (hwiNum >= (HWI_HANDLE_T) HalGicGetMaxIrqNum()) {
        return OS_ERRNO_HWI_NUM_INVALID;
    }

    HalGicIrqMask(LOSCFG_PLATFORM_GIC_SEQUENCE, hwiNum);
    return LOS_OK;
}

/* 中断挂起. */
STATIC UINT32 HwiPending(HWI_HANDLE_T hwiNum)
{
    if (hwiNum >= OS_HWI_MAX_NUM) {
        return OS_ERRNO_HWI_NUM_INVALID;
    }

    if (hwiNum >= (HWI_HANDLE_T) HalGicGetMaxIrqNum()) {
        return OS_ERRNO_HWI_NUM_INVALID;
    }

    HalGicSetPendingIrq(LOSCFG_PLATFORM_GIC_SEQUENCE, hwiNum);
    return LOS_OK;
}

/* 中断清除. */
STATIC UINT32 HwiClear(HWI_HANDLE_T hwiNum)
{
    if (hwiNum >= OS_HWI_MAX_NUM) {
        return OS_ERRNO_HWI_NUM_INVALID;
    }

    if (hwiNum >= (HWI_HANDLE_T) HalGicGetMaxIrqNum()) {
        return OS_ERRNO_HWI_NUM_INVALID;
    }

    HalGicClearPendingIrq(LOSCFG_PLATFORM_GIC_SEQUENCE, hwiNum);
    return LOS_OK;
}

/* 获取中断号. */
STATIC UINT32 HwiNumGet(VOID)
{
    return g_hwiCb.curHwiNum;
}

HwiControllerOps g_archHwiOps = {
    .enableIrq      = HwiUnmask,
    .disableIrq     = HwiMask,
    .setIrqPriority = HwiSetPriority,
    .getCurIrqNum   = HwiNumGet,
    .triggerIrq     = HwiPending,
    .clearIrq       = HwiClear,
};


/* 注册中断处理函数. */
#if (LOSCFG_PLATFORM_HWI_WITH_ARG == 1)
VOID OsSetVector(UINTPTR num, HWI_PROC_FUNC vector, VOID *arg)
{
    if (num < OS_HWI_MAX_NUM) {
        g_hwiCb.handler[num].fn = vector;
        g_hwiCb.handler[num].parm = arg;
    }
}
#else
VOID OsSetVector(UINTPTR num, HWI_PROC_FUNC vector)
{
    if (num < OS_HWI_MAX_NUM) {
        g_hwiCb.handler[num].fn = vector;
        g_hwiCb.handler[num].parm = NULL;
    }
}
#endif

/* 默认中断处理函数. */
#if (LOSCFG_PLATFORM_HWI_WITH_ARG == 1)
LITE_OS_SEC_TEXT_MINOR VOID HalHwiDefaultHandler(VOID *parm)
{
    UINT32 hwiNum = HwiNumGet();

    (VOID)parm;

    if (hwiNum >= OS_HWI_MAX_NUM) {
        return;
    }

    if (hwiNum >= (HWI_HANDLE_T) HalGicGetMaxIrqNum()) {
        return;
    }

    PRINT_ERR("%s() The interrupt handler was not registered, intId = %u\n", __FUNCTION__, hwiNum);
}
#else
LITE_OS_SEC_TEXT_MINOR VOID HalHwiDefaultHandler(VOID)
{
    UINT32 hwiNum = HwiNumGet();

    (VOID)parm;

    if (hwiNum >= OS_HWI_MAX_NUM) {
        return;
    }

    if (hwiNum >= (HWI_HANDLE_T) HalGicGetMaxIrqNum()) {
        return;
    }

    PRINT_ERR("%s() The interrupt handler was not registered, intId = %u\n", __FUNCTION__, hwiNum);
}
#endif

/* 异常管理初始化. */
LITE_OS_SEC_TEXT_INIT VOID HalHwiInit(VOID)
{
    HalGicInit(LOSCFG_PLATFORM_GIC_SEQUENCE, 0);
    memset_s(&g_hwiCb, sizeof(g_hwiCb), 0, sizeof(g_hwiCb));
    for (UINT32 index = 0; index < OS_HWI_MAX_NUM; index++) {
        g_hwiCb.handler[index].fn = HalHwiDefaultHandler;
    }
}

/* 创建中断. */
LITE_OS_SEC_TEXT_INIT UINT32 ArchHwiCreate(HWI_HANDLE_T hwiNum,
                                           HWI_PRIOR_T hwiPrio,
                                           HWI_MODE_T hwiMode,
                                           HWI_PROC_FUNC hwiHandler,
                                           HwiIrqParam *irqParam)
{
    (VOID)hwiMode;

    if (hwiHandler == NULL) {
        return OS_ERRNO_HWI_PROC_FUNC_NULL;
    }

    if (hwiNum >= OS_HWI_MAX_NUM) {
        return OS_ERRNO_HWI_NUM_INVALID;
    }

    if (hwiPrio > OS_HWI_PRIO_LOWEST) {
        return OS_ERRNO_HWI_PRIO_INVALID;
    }

    HalGicInit(LOSCFG_PLATFORM_GIC_SEQUENCE, 0);
    if (hwiNum >= (HWI_HANDLE_T) HalGicGetMaxIrqNum()) {
        return OS_ERRNO_HWI_NUM_INVALID;
    }

    if (g_hwiCb.handler[hwiNum].fn != HalHwiDefaultHandler) {
        return OS_ERRNO_HWI_ALREADY_CREATED;
    }

    UINTPTR intSave = LOS_IntLock();
#if (LOSCFG_PLATFORM_HWI_WITH_ARG == 1)
    if ((irqParam != NULL) && (irqParam->pDevId != NULL)) {
        OsSetVector(hwiNum, hwiHandler, irqParam->pDevId);
    } else {
        OsSetVector(hwiNum, hwiHandler, NULL);
    }
#else
    (VOID)irqParam;
    OsSetVector(hwiNum, hwiHandler);
#endif

#if (LOSCFG_DEBUG_TOOLS == 1)
    if ((irqParam != NULL) && (irqParam->pName != NULL)) {
        g_hwiCb.name[hwiNum] = (CHAR *)irqParam->pName;
    }
    g_hwiCb.triggerCnt[hwiNum] = 0;
#endif

    HwiSetTargetCPU(hwiNum, HalGetCpuId());
    HwiSetPriority(hwiNum, hwiPrio);
    HwiUnmask(hwiNum);

    LOS_IntRestore(intSave);

    return LOS_OK;
}

/* 删除中断. */
LITE_OS_SEC_TEXT_INIT UINT32 ArchHwiDelete(HWI_HANDLE_T hwiNum, HwiIrqParam *irqParam)
{
    (VOID)irqParam;

    if (hwiNum >= OS_HWI_MAX_NUM) {
        return OS_ERRNO_HWI_NUM_INVALID;
    }

    if (hwiNum >= (HWI_HANDLE_T) HalGicGetMaxIrqNum()) {
        return OS_ERRNO_HWI_NUM_INVALID;
    }

    HwiMask(hwiNum);

    UINTPTR intSave = LOS_IntLock();
    g_hwiCb.handler[hwiNum].fn = HalHwiDefaultHandler;
    g_hwiCb.handler[hwiNum].parm = NULL;
    LOS_IntRestore(intSave);

    return LOS_OK;
}

WEAK VOID HalPreInterruptHandler(UINT32 arg)
{
    (VOID)arg;
    return;
}

WEAK VOID HalAftInterruptHandler(UINT32 arg)
{
    (VOID)arg;
    return;
}

/* 异常处理统一入口. */
LITE_OS_SEC_TEXT VOID HalInterrupt(UINTPTR hwiIndex)
{
    UINTPTR intSave;

    intSave = LOS_IntLock();
    g_intCount++;
    LOS_IntRestore(intSave);

    if (hwiIndex >= OS_HWI_MAX_NUM) {
        PRINTK("Interrupt %u is triggered.\n", hwiIndex);
        goto EXIT;
    }

    g_hwiCb.curHwiNum = (UINT32) hwiIndex;
    OsHookCall(LOS_HOOK_TYPE_ISR_ENTER, hwiIndex);

#if (LOSCFG_CPUP_INCLUDE_IRQ == 1)
    OsCpupIrqStart(hwiIndex);
#endif

    HalPreInterruptHandler(hwiIndex);

if (g_hwiCb.handler[hwiIndex].fn != 0) {
#if (LOSCFG_PLATFORM_HWI_WITH_ARG == 1)
        g_hwiCb.handler[hwiIndex].fn((VOID *)g_hwiCb.handler[hwiIndex].parm);
#else
        g_hwiCb.handler[hwiIndex].fn();
#endif
    }

#if (LOSCFG_DEBUG_TOOLS == 1)
    ++g_hwiCb.triggerCnt[hwiIndex];
#endif

    HalAftInterruptHandler(hwiIndex);

#if (LOSCFG_CPUP_INCLUDE_IRQ == 1)
    OsCpupIrqEnd(hwiIndex);
#endif

    OsHookCall(LOS_HOOK_TYPE_ISR_EXIT, hwiIndex);
    g_hwiCb.curHwiNum = 0;

EXIT:
    intSave = LOS_IntLock();
    g_intCount--;
    LOS_IntRestore(intSave);
}

/* 判断是否正在中断处理中. */
UINT32 ArchIsIntActive(VOID)
{
    return (g_intCount > 0);
}

#if (LOSCFG_DEBUG_TOOLS == 1)
/* 判断中断是否被创建. */
BOOL OsGetHwiCreated(UINT32 index)
{
    if (g_hwiCb.handler[index].fn != HalHwiDefaultHandler) {
        return TRUE;
    }

    return FALSE;
}

/* 获取中断名称. */
CHAR *OsGetHwiFormName(UINT32 index)
{
    return g_hwiCb.name[index];
}

/* 获取中断触发次数. */
UINT32 OsGetHwiFormCnt(UINT32 index)
{
    return g_hwiCb.triggerCnt[index];
}
#endif


#if (LOSCFG_KERNEL_PRINTF != 0)
STATIC VOID OsExcFaultStatus(UINT8 faultStatus, UINTPTR faultAddr)
{
    switch (faultStatus) {
        case OS_FS_ALIGNMENT_FAULT:
            PRINTK("Alignment Fault @ 0x%08" PRIxPTR "\n", faultAddr);
            break;
        case OS_FS_BACKGROUND_FAULT:
            PRINTK("Background Fault @ 0x%08" PRIxPTR "\n", faultAddr);
            break;
        case OS_FS_PERMISSION_FAULT:
            PRINTK("Permission Fault @ 0x%08" PRIxPTR "\n", faultAddr);
            break;
        case OS_FS_SYNC_EXTERNAL_ABORT:
            PRINTK("Synchronous External Abort @ 0x%08" PRIxPTR "\n", faultAddr);
            break;
        case OS_FS_ASYNC_EXTERNAL_ABORT:
            PRINTK("Asynchronous External Abort\n");
            break;
        case OS_FS_SYNC_PARITY_ERROR:
            PRINTK("Synchronous Parity/ECC Error @ 0x%08" PRIxPTR "\n", faultAddr);
            break;
        case OS_FS_ASYNC_PARITY_ERROR:
            PRINTK("Asynchronous Parity/ECC Error\n");
            break;
        case OS_FS_DEBUG_EVENT:
            PRINTK("Debug Event\n");
            break;
        case OS_FS_ACCESS_FLAG_FAULT_1ST:
        case OS_FS_ACCESS_FLAG_FAULT_2ND:
            PRINTK("Access Flag Fault @ 0x%08" PRIxPTR "\n", faultAddr);
            break;
        case OS_FS_TRANSLATION_FAULT_1ST:
        case OS_FS_TRANSLATION_FAULT_2ND:
            PRINTK("Translation Fault @ 0x%08" PRIxPTR "\n", faultAddr);
            break;
        default:
            PRINTK("Unknown (%u)", faultStatus);
    }
}

STATIC VOID OsExcFaultInfo(UINT8 excType, UINT8 faultStatus, UINTPTR faultAddr)
{
    if (excType == OS_EXCEPT_UNDEF_INSTR) {
        PRINTK("Undefined instruction exception:\n");
    } else if (excType == OS_EXCEPT_PREFETCH_ABORT) {
        PRINTK("Prefetch abort exception:\n");
        OsExcFaultStatus(faultStatus, faultAddr);
    } else if (excType == OS_EXCEPT_DATA_ABORT) {
        PRINTK("Data abort exception:\n");
        OsExcFaultStatus(faultStatus, faultAddr);
    } else {
        PRINTK("Unknown exception (%u):\n", excType);
    }
}

STATIC VOID OsExcTypeInfo(const ExcInfo *excInfo)
{
    const char *phaseStr[] = {"exc in init", "exc in task", "exc in hwi"};
    UINT8 excType = (UINT8) (excInfo->type >> 8);
    UINT8 faultStatus = (UINT8) excInfo->type;

    OsExcFaultInfo(excType, faultStatus, excInfo->faultAddr);
    PRINTK("Type      = %u\n", excType);
    PRINTK("ThrdPid   = %u\n", excInfo->thrdPid);
    PRINTK("Phase     = %s\n", phaseStr[excInfo->phase]);
    PRINTK("FaultAddr = 0x%08" PRIxPTR "\n", excInfo->faultAddr);
}

STATIC VOID OsExcCurTaskInfo(const ExcInfo *excInfo)
{
    if (excInfo->phase == OS_EXC_IN_TASK) {
        PRINTK("Current task info:\n");
        LosTaskCB *taskCB = OS_TCB_FROM_TID(LOS_CurTaskIDGet());
        PRINTK("Task name = %s\n", taskCB->taskName);
        PRINTK("Task ID   = %u\n", taskCB->taskID);
        PRINTK("Task SP   = %p\n", taskCB->stackPointer);
        PRINTK("Task ST   = 0x%08" PRIxPTR "\n", taskCB->topOfStack);
        PRINTK("Task SS   = 0x%x\n", taskCB->stackSize);
    } else if (excInfo->phase == OS_EXC_IN_HWI) {
        PRINTK("Exception occur in interrupt phase!\n");
    } else {
        PRINTK("Exception occur in system init phase!\n");
    }
}

STATIC VOID OsExcRegInfo(const ExcInfo *excInfo)
{
    PRINTK("Exception reg dump:\n");
    PRINTK("PC   = 0x%08" PRIxPTR "\n", excInfo->context->pc);
    PRINTK("LR   = 0x%08" PRIxPTR "\n", excInfo->context->lr);
    PRINTK("SP   = 0x%08" PRIxPTR "\n", excInfo->context->sp);
    PRINTK("R0   = 0x%08" PRIxPTR "\n", excInfo->context->r0);
    PRINTK("R1   = 0x%08" PRIxPTR "\n", excInfo->context->r1);
    PRINTK("R2   = 0x%08" PRIxPTR "\n", excInfo->context->r2);
    PRINTK("R3   = 0x%08" PRIxPTR "\n", excInfo->context->r3);
    PRINTK("R4   = 0x%08" PRIxPTR "\n", excInfo->context->r4);
    PRINTK("R5   = 0x%08" PRIxPTR "\n", excInfo->context->r5);
    PRINTK("R6   = 0x%08" PRIxPTR "\n", excInfo->context->r6);
    PRINTK("R7   = 0x%08" PRIxPTR "\n", excInfo->context->r7);
    PRINTK("R8   = 0x%08" PRIxPTR "\n", excInfo->context->r8);
    PRINTK("R9   = 0x%08" PRIxPTR "\n", excInfo->context->r9);
    PRINTK("R10  = 0x%08" PRIxPTR "\n", excInfo->context->r10);
    PRINTK("R11  = 0x%08" PRIxPTR "\n", excInfo->context->r11);
    PRINTK("R12  = 0x%08" PRIxPTR "\n", excInfo->context->r12);
    PRINTK("SPSR = 0x%08" PRIxPTR "\n", excInfo->context->spsr);
}

#if (LOSCFG_KERNEL_BACKTRACE == 1)
STATIC VOID OsExcBackTraceInfo(const ExcInfo *excInfo)
{
    CHAR buffer[LOSCFG_BACKTRACE_DEPTH * 9 + 1] = {0};
    UINTPTR LR[LOSCFG_BACKTRACE_DEPTH] = {0};
    UINT32 index;

    OsBackTraceHookCall(LR, LOSCFG_BACKTRACE_DEPTH, 0, excInfo->context->sp);

    PRINTK("----- backtrace start -----\n");
    PRINTK("backtrace 0 -- lr = 0x%08" PRIxPTR "\n", excInfo->context->lr);
    for (index = 0; index < LOSCFG_BACKTRACE_DEPTH; index++) {
        if (LR[index] == 0) {
            break;
        }
        PRINTK("backtrace %u -- lr = 0x%08" PRIxPTR "\n", index + 1, LR[index]);
        sprintf_s(&buffer[index * 9], 10, " %08" PRIxPTR, LR[index]);
    }
    PRINTK("----- backtrace end -----\n");

#if defined(LOSCFG_PRODUCT) && defined(LOSCFG_BOARD)
    PRINTK("\n%saddr2line -e out/%s/%s/OHOS_Image -a -f %08" PRIxPTR "%s\n",
        LOSCFG_CROSS_COMPILE, LOSCFG_BOARD, LOSCFG_PRODUCT, excInfo->context->lr, buffer);
#else
    PRINTK("\n%saddr2line -e OHOS_Image -a -f %08" PRIxPTR "%s\n",
        LOSCFG_CROSS_COMPILE, excInfo->context->lr, buffer);
#endif
}
#endif

STATIC VOID OsExcMemPoolCheckInfo(VOID)
{
    PRINTK("\nmemory pools check:\n");
#if (LOSCFG_PLATFORM_EXC == 1)
    MemInfoCB memExcInfo[OS_SYS_MEM_NUM];

    (VOID)memset_s(memExcInfo, sizeof(memExcInfo), 0, sizeof(memExcInfo));

    UINT32 errCnt = OsMemExcInfoGet(OS_SYS_MEM_NUM, memExcInfo);
    if (errCnt < OS_SYS_MEM_NUM) {
        errCnt += OsMemboxExcInfoGet(OS_SYS_MEM_NUM - errCnt, memExcInfo + errCnt);
    }

    if (errCnt == 0) {
        PRINTK("all memory pool check passed!\n");
        return;
    }

    for (UINT32 i = 0; i < errCnt; i++) {
        PRINTK("pool num              = %u\n", i);
        PRINTK("pool type             = %u\n", memExcInfo[i].type);
        PRINTK("pool addr             = 0x%08" PRIxPTR "\n", memExcInfo[i].startAddr);
        PRINTK("pool size             = 0x%" PRIxPTR "\n", memExcInfo[i].size);
        PRINTK("pool free             = 0x%" PRIxPTR "\n", memExcInfo[i].free);
        PRINTK("pool blkNum           = %u\n", memExcInfo[i].blockSize);
        PRINTK("pool error node addr  = 0x%08" PRIxPTR "\n", memExcInfo[i].errorAddr);
        PRINTK("pool error node len   = 0x%" PRIxPTR "\n", memExcInfo[i].errorLen);
        PRINTK("pool error node owner = %u\n", memExcInfo[i].errorOwner);
    }
#endif
    UINT32 ret = LOS_MemIntegrityCheck(LOSCFG_SYS_HEAP_ADDR);
    if (ret == LOS_OK) {
        PRINTK("system heap memcheck over, all passed!\n");
    }

    PRINTK("memory pool check end!\n");
}
#endif

STATIC VOID OsExcInfoDisplay(const ExcInfo *excInfo)
{
#if (LOSCFG_KERNEL_PRINTF != 0)
    PRINTK("*************Exception Information**************\n");
    OsExcTypeInfo(excInfo);
    OsExcCurTaskInfo(excInfo);
    OsExcRegInfo(excInfo);
#if (LOSCFG_KERNEL_BACKTRACE == 1)
    OsExcBackTraceInfo(excInfo);
#endif
    OsGetAllTskInfo();
    OsExcMemPoolCheckInfo();
#endif
}

LITE_OS_SEC_TEXT_INIT VOID HalExcHandleEntry(UINTPTR excType, EXC_CONTEXT_S *excBufAddr, UINTPTR esr, UINTPTR far)
{
    g_intCount++;
    g_excInfo.nestCnt++;

    g_excInfo.context = excBufAddr;
    g_excInfo.type = (UINT16) (excType << 8);
    if (excType == OS_EXCEPT_UNDEF_INSTR) {
        g_excInfo.faultAddr = OS_EXC_IMPRECISE_ACCESS_ADDR;
        if ((excBufAddr->spsr & OS_INSTR_SET_MASK) == 0) { /* Work status: ARM */
            excBufAddr->pc -= OS_ARM_INSTR_LEN;
        } else if ((excBufAddr->spsr & OS_INSTR_SET_MASK) == 0x20) { /* Work status: Thumb */
            excBufAddr->pc -= OS_THUMB_INSTR_LEN;
        }
    } else if (excType == OS_EXCEPT_PREFETCH_ABORT || excType == OS_EXCEPT_DATA_ABORT) {
        g_excInfo.reserved = excType; /* 保留异常类型, 用于异常嵌套时确定产生异常的异常类型. */
        g_excInfo.type |= (UINT16) (((esr & (1 << 10)) >> 6) | (esr & 0xf));
        g_excInfo.faultAddr = (esr & (1 << 16)) ? OS_EXC_IMPRECISE_ACCESS_ADDR : far;
    }

    /* 根据异常产生时的工作模式判断异常是否在异常处理时产生. */
    UINT8 mode = (UINT8) (excBufAddr->spsr & OS_EXC_MODE_SYS32);
    if ((mode != OS_EXC_MODE_USR32) && (mode != OS_EXC_MODE_SYS32)) {
        g_excInfo.phase = OS_EXC_IN_HWI;
        if (mode == OS_EXC_MODE_IRQ32 || mode == OS_EXC_MODE_FIQ32) {
            g_excInfo.thrdPid = g_hwiCb.curHwiNum;
        } else if (mode == OS_EXC_MODE_UND32) {
            g_excInfo.thrdPid = OS_EXCEPT_UNDEF_INSTR;
        } else if (mode == OS_EXC_MODE_SVC32) {
            g_excInfo.thrdPid = OS_EXCEPT_SWI;
        } else if (mode == OS_EXC_MODE_ABT32) {
            g_excInfo.thrdPid = g_excInfo.reserved;
            g_excInfo.reserved = 0;
        }
    } else if (LOS_TaskIsRunning()) {
        g_excInfo.phase = OS_EXC_IN_TASK;
        g_excInfo.thrdPid = g_losTask.runTask->taskID;
        excBufAddr->sp = (UINT32) g_losTask.runTask->stackPointer;
    } else {
        g_excInfo.phase = OS_EXC_IN_INIT;
        g_excInfo.thrdPid = OS_NULL_INT;
    }

    OsDoExcHook(EXC_INTERRUPT);
    OsExcInfoDisplay(&g_excInfo);
    ArchSysExit();
}

